package com.ruicar.afs.jobadmin.core.thread;

import com.ruicar.afs.jobadmin.core.conf.JobAdminConfig;
import com.ruicar.afs.jobadmin.core.model.AfsJobGroup;
import com.ruicar.afs.jobadmin.core.model.AfsJobRegistry;
import com.ruicar.afs.cloud.common.job.core.enums.RegistryConfig;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.*;
import java.util.concurrent.TimeUnit;

/**
 * The type JobRegistryMonitorHelper
 * <p>Description: </p>
 *
 * @author Fzero
 * @version 1.0
 * @date Created on 2020.06.13 14:17:11
 * @since 1.0
 */
public class JobRegistryMonitorHelper {
    /**
     * Logger
     * <p>Description: </p>
     */
    private static Logger logger = LoggerFactory.getLogger(JobRegistryMonitorHelper.class);

    /**
     * Instance
     * <p>Description: </p>
     */
    private static JobRegistryMonitorHelper instance = new JobRegistryMonitorHelper();

    /**
     * Gets instance *
     *
     * @return the instance
     */
    public static JobRegistryMonitorHelper getInstance() {
        return instance;
    }

    /**
     * Registry thread
     * <p>Description: </p>
     */
    private Thread registryThread;
    /**
     * To stop
     * <p>Description: </p>
     */
    private volatile boolean toStop = false;

    /**
     * Start
     */
    public void start() {
        registryThread = new Thread(new Runnable() {
            @Override
            public void run() {
                while (!toStop) {
                    try {
                        // auto registry group
                        List<AfsJobGroup> groupList = JobAdminConfig.getAdminConfig().getAfsJobGroupMapper().findByAddressType(0);
                        if (groupList != null && !groupList.isEmpty()) {

                            // remove dead address (admin/executor)
                            List<Integer> ids = JobAdminConfig.getAdminConfig().getAfsJobRegistryMapper().findDead(RegistryConfig.DEAD_TIMEOUT, new Date());
                            if (ids != null && ids.size() > 0) {
                                JobAdminConfig.getAdminConfig().getAfsJobRegistryMapper().removeDead(ids);
                            }

                            // fresh online address (admin/executor)
                            HashMap<String, List<String>> appAddressMap = new HashMap<String, List<String>>();
                            List<AfsJobRegistry> list = JobAdminConfig.getAdminConfig().getAfsJobRegistryMapper().findAll(RegistryConfig.DEAD_TIMEOUT, new Date());
                            if (list != null) {
                                for (AfsJobRegistry item : list) {
                                    if (RegistryConfig.RegistryType.EXECUTOR.name().equals(item.getRegistryGroup())) {
                                        String appName = item.getRegistryKey();
                                        List<String> registryList = appAddressMap.get(appName);
                                        if (registryList == null) {
                                            registryList = new ArrayList<String>();
                                        }

                                        if (!registryList.contains(item.getRegistryValue())) {
                                            registryList.add(item.getRegistryValue());
                                        }
                                        appAddressMap.put(appName, registryList);
                                    }
                                }
                            }

                            // fresh group address
                            for (AfsJobGroup group : groupList) {
                                List<String> registryList = appAddressMap.get(group.getAppName());
                                String addressListStr = null;
                                if (registryList != null && !registryList.isEmpty()) {
                                    Collections.sort(registryList);
                                    addressListStr = "";
                                    for (String item : registryList) {
                                        addressListStr += item + ",";
                                    }
                                    addressListStr = addressListStr.substring(0, addressListStr.length() - 1);
                                }
                                group.setAddressList(addressListStr);
                                JobAdminConfig.getAdminConfig().getAfsJobGroupMapper().update(group);
                            }
                        }
                    } catch (Exception e) {
                        if (!toStop) {
                            logger.error(">>>>>>>>>>> afs-job, job registry monitor thread error:{}", e);
                        }
                    }
                    try {
                        TimeUnit.SECONDS.sleep(RegistryConfig.BEAT_TIMEOUT);
                    } catch (InterruptedException e) {
                        if (!toStop) {
                            logger.error(">>>>>>>>>>> afs-job, job registry monitor thread error:{}", e);
                        }
                    }
                }
                logger.info(">>>>>>>>>>> afs-job, job registry monitor thread stop");
            }
        });
        registryThread.setDaemon(true);
        registryThread.setName("afs-job, admin JobRegistryMonitorHelper");
        registryThread.start();
    }

    /**
     * To stop
     */
    public void toStop() {
        toStop = true;
        // interrupt and wait
        registryThread.interrupt();
        try {
            registryThread.join();
        } catch (InterruptedException e) {
            logger.error(e.getMessage(), e);
        }
    }

}
